/**
 * 分片上传工具类
 * 对接后端分片上传API
 */
class ChunkUploader {
    constructor(options = {}) {
        this.baseUrl = options.baseUrl || '/api/notebook/environment';
        this.chunkSize = options.chunkSize || 2 * 1024 * 1024; // 默认2MB
        this.maxRetries = options.maxRetries || 1;
        this.onProgress = options.onProgress || (() => {});
        this.onSuccess = options.onSuccess || (() => {});
        this.onError = options.onError || (() => {});
        this.onStatusUpdate = options.onStatusUpdate || (() => {});
    }

    /**
     * 生成文件ID
     */
    generateFileId() {
        return 'file_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
    }

    /**
     * 计算文件分片信息
     */
    calculateChunks(file) {
        const totalChunks = Math.ceil(file.size / this.chunkSize);
        const chunks = [];
        
        for (let i = 0; i < totalChunks; i++) {
            const start = i * this.chunkSize;
            const end = Math.min(start + this.chunkSize, file.size);
            chunks.push({
                index: i,
                start: start,
                end: end,
                size: end - start,
                blob: file.slice(start, end)
            });
        }
        
        return {
            totalChunks,
            chunks
        };
    }

    /**
     * 上传单个分片
     */
    async uploadChunk(fileId, fileName, chunk, totalChunks, projectId = 'default', userId = 'user1') {
        const formData = new FormData();
        formData.append('file', chunk.blob, `${fileName}.part${chunk.index}`);
        formData.append('projectId', projectId);
        formData.append('userId', userId);
        formData.append('fileSize', chunk.blob.size);
        formData.append('mimeType', chunk.blob.type || 'application/octet-stream');

        const response = await fetch(`${this.baseUrl}/upload`, {
            method: 'POST',
            headers: {
                'file_id': fileId,
                'file_name': fileName,
                'chunk_number': chunk.index.toString(),
                'total_chunks': totalChunks.toString()
            },
            body: formData,
            // 允许跨域请求携带Cookie（如果需要）
            credentials: 'include',
            // 明确跨域模式
            mode: 'cors'
        });

        if (!response.ok) {
            throw new Error(`分片 ${chunk.index} 上传失败: ${response.statusText}`);
        }

        return await response.json();
    }

    /**
     * 查询上传状态
     */
    async getUploadStatus(fileId) {
        const response = await fetch(`${this.baseUrl}/upload/status/${fileId}`, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json'
            },
            credentials: 'include',
            mode: 'cors'
        });

        if (!response.ok) {
            throw new Error(`查询状态失败: ${response.statusText}`);
        }

        return await response.json();
    }

    /**
     * 主上传方法
     */
    async upload(file, options = {}) {
        const fileId = this.generateFileId();
        const fileName = file.name;
        const projectId = options.projectId || 'default';
        const userId = options.userId || 'user1';
        
        try {
            // 计算分片
            const { totalChunks, chunks } = this.calculateChunks(file);
            
            this.onStatusUpdate({
                fileId,
                fileName,
                status: 'UPLOADING',
                totalChunks,
                uploadedChunks: 0,
                progress: 0
            });

            let uploadedChunks = 0;
            const failedChunks = [];

            // 并发上传分片（限制并发数）
            const concurrency = 3;
            for (let i = 0; i < chunks.length; i += concurrency) {
                const batch = chunks.slice(i, i + concurrency);
                const promises = batch.map(chunk => 
                    this.uploadChunkWithRetry(fileId, fileName, chunk, totalChunks, projectId, userId)
                );

                try {
                    const results = await Promise.allSettled(promises);
                    
                    results.forEach((result, index) => {
                        const chunkIndex = i + index;
                        if (result.status === 'fulfilled') {
                            uploadedChunks++;
                            const progress = (uploadedChunks / totalChunks) * 100;
                            this.onProgress({
                                fileId,
                                fileName,
                                uploadedChunks,
                                totalChunks,
                                progress: Math.round(progress * 100) / 100
                            });
                        } else {
                            failedChunks.push(chunkIndex);
                            console.error(`分片 ${chunkIndex} 上传失败:`, result.reason);
                        }
                    });
                } catch (error) {
                    console.error('批次上传失败:', error);
                }
            }

            // 检查是否所有分片都上传成功
            if (failedChunks.length > 0) {
                throw new Error(`${failedChunks.length} 个分片上传失败`);
            }

            // 轮询检查合并状态
            await this.waitForMergeComplete(fileId);

            this.onSuccess({
                fileId,
                fileName,
                message: '文件上传成功'
            });

            return { fileId, fileName, success: true };

        } catch (error) {
            this.onError({
                fileId,
                fileName,
                error: error.message
            });
            throw error;
        }
    }

    /**
     * 带重试的分片上传
     */
    async uploadChunkWithRetry(fileId, fileName, chunk, totalChunks, projectId, userId) {
        let lastError;
        
        for (let retry = 0; retry < this.maxRetries; retry++) {
            try {
                return await this.uploadChunk(fileId, fileName, chunk, totalChunks, projectId, userId);
            } catch (error) {
                lastError = error;
                console.warn(`分片 ${chunk.index} 第 ${retry + 1} 次上传失败:`, error.message);
                
                if (retry < this.maxRetries - 1) {
                    // 等待一段时间后重试
                    await new Promise(resolve => setTimeout(resolve, 1000 * (retry + 1)));
                }
            }
        }
        
        throw lastError;
    }

    /**
     * 等待文件合并完成
     */
    async waitForMergeComplete(fileId, maxWaitTime = 30000) {
        const startTime = Date.now();
        
        while (Date.now() - startTime < maxWaitTime) {
            try {
                const status = await this.getUploadStatus(fileId);
                
                this.onStatusUpdate(status);
                
                if (status.status === 'COMPLETED') {
                    return status;
                } else if (status.status === 'FAILED') {
                    throw new Error('文件合并失败');
                }
                
                // 等待1秒后再次查询
                await new Promise(resolve => setTimeout(resolve, 1000));
            } catch (error) {
                console.warn('查询状态失败:', error.message);
                await new Promise(resolve => setTimeout(resolve, 2000));
            }
        }
        
        throw new Error('等待文件合并超时');
    }

    /**
     * 格式化文件大小
     */
    static formatFileSize(bytes) {
        if (bytes === 0) return '0 Bytes';
        
        const k = 1024;
        const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        
        return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    }

    /**
     * 验证文件类型
     */
    static validateFile(file, allowedTypes = [], maxSize = null) {
        const errors = [];
        
        if (allowedTypes.length > 0) {
            const fileExtension = file.name.split('.').pop().toLowerCase();
            const mimeType = file.type.toLowerCase();
            
            const isValidType = allowedTypes.some(type => {
                if (type.startsWith('.')) {
                    return fileExtension === type.substring(1);
                } else {
                    return mimeType.includes(type);
                }
            });
            
            if (!isValidType) {
                errors.push(`不支持的文件类型: ${file.type || '未知'}`);
            }
        }
        
        if (maxSize && file.size > maxSize) {
            errors.push(`文件大小超过限制: ${ChunkUploader.formatFileSize(file.size)} > ${ChunkUploader.formatFileSize(maxSize)}`);
        }
        
        return {
            valid: errors.length === 0,
            errors
        };
    }
}

// 导出类
if (typeof module !== 'undefined' && module.exports) {
    module.exports = ChunkUploader;
} else {
    window.ChunkUploader = ChunkUploader;
}

